package com.example.szl7033.beauty1;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }
    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    //for test
    public native String stringFromJNI();
    //only for preview
    public native void previewProcess(byte[] bytes,int width,int height);
    public native void previewInit(int width,int height);
    public native void previewUninit();

    /**
     * 全局变量
     */

    private static final String TAG = "shi_log";
    private Camera mCamera;
    private SurfaceView mSurfaceView;
    private SurfaceHolder mSurfaceHolder;

    private Camera.Size previewSize = null; //预览尺寸
    private Camera.Size pictureSize = null; //照片尺寸

    /**
     * 活动状态变化
     */

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //动态权限检测
        checkPermission();

        Log.d(TAG,stringFromJNI());

        //获取相机实例
        mCamera = getCameraInstance();
        //打印相机支持的参数设置
        printCameraParameters();
        //调整相机显示角度
        mCamera.setDisplayOrientation(90);  //竖屏

        //获取图像载体实例（相对与活动而言）
        mSurfaceView = new SurfaceView(this);
        //获取图像载体的控制器
        mSurfaceHolder = mSurfaceView.getHolder();
        //为图像载体添加状态回调
        mSurfaceHolder.addCallback(mSurfaceHolder_Callback);

        //获取显示控件实例（画图）
        FrameLayout preview = findViewById(R.id.camera_preview);
        //添加设置 SurfaceView 的属性参数
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(480,640);
        //Log.d(TAG,"parent:" + ViewGroup.LayoutParams.MATCH_PARENT + "x" + ViewGroup.LayoutParams.MATCH_PARENT);
        //添加获取图像的来源（从 mSurfaceView 获取原始图像，绘制到控件内）
        preview.addView(mSurfaceView,params);
        //Log.d(TAG,"parent:" + mSurfaceView.getWidth() + "x" + mSurfaceView.getHeight());

        //获取按钮实例
        Button button = findViewById(R.id.button_capture);
        //设置按钮点击监听
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mCamera.takePicture(null,null,mCamera_PictureCallback);
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        mCamera.release();

        mCamera = null;
        mSurfaceView = null;
    }

    /**
     * 回调处理对象
     */

    //表面控制器回调（图像载体状态变化回调）
    private SurfaceHolder.Callback mSurfaceHolder_Callback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
            try {
                mCamera.setPreviewDisplay(mSurfaceHolder);
                //设置预览内容，绑定Camera和SurfaceHolder（SurfaceView 将从 Camera 底层获取图像数据）
                mCamera.setPreviewCallback(mCamera_PreviewCallback);    //设置预览回调
                updateCameraParameters();                               //设置（照片/预览/控件）尺寸
                previewInit(previewSize.width,previewSize.height);      //预览图像处理算法初始化（包括打开文件）
                mCamera.startPreview();                                 //开始预览
            } catch (IOException e) {
                Log.d(TAG, "相机开始预览错误！！！" + e.getMessage());
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
            if(mSurfaceHolder.getSurface() == null){
                //图像载体的输出（显示控件）不存在
                return;
            }

            //在图像载体改变之前，停止预览（预览参数需要重新设置，必须停止预览）
            mCamera.stopPreview();//停止预览

            //重新设置预览参数，重新开始预览
            try {
                mCamera.setPreviewDisplay(mSurfaceHolder);          //设置预览内容的来源
                mCamera.setPreviewCallback(mCamera_PreviewCallback);//设置预览回调
                updateCameraParameters();                           //设置（照片/预览/控件）尺寸
                mCamera.startPreview();                             //开始预览
            } catch (Exception e){
                Log.d(TAG, "相机开始预览错误！！！ " + e.getMessage());
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
            mCamera.stopPreview();              //停止预览
            try {
                mCamera.setPreviewDisplay(null);//停止图像底层输出
            } catch (IOException e) {
                e.printStackTrace();
            }
            mCamera.setPreviewCallback(null);   //停止预览回调
            previewUninit();                    //释放预览处理算法资源（包括关闭文件）
        }
    };

    //相机预览回调
    private Camera.PreviewCallback mCamera_PreviewCallback = new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] bytes, Camera camera) {
            //调用预览帧处理函数（在C/C++层保存数据）
            previewProcess(bytes,previewSize.width,previewSize.height);
            //调用预览帧保存函数
            //onGetYUVFrame(bytes);
        }
    };

    //相机拍照回调
    private Camera.PictureCallback mCamera_PictureCallback = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] bytes, Camera camera) {
            //调用照片处理函数（无法执行，格式不支持）
            //pictureProcess();
            //调用照片保存函数
            onTakePicture(bytes);
        }
    };

    /**
     * 处理函数
     */

    //动态权限检测
    private void checkPermission(){
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M){
            return;
        }
        String[] permission = new String[]{
                Manifest.permission.CAMERA,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_EXTERNAL_STORAGE
        };
        List<String> mPermissionList = new ArrayList<>();
        mPermissionList.clear();
        for (String aPermission : permission) {
            if (ContextCompat.checkSelfPermission(MainActivity.this, aPermission) != PackageManager.PERMISSION_GRANTED) {
                mPermissionList.add(aPermission);
            }
        }
        if (mPermissionList.isEmpty()) {//未授予的权限为空，表示都授予了
            Toast.makeText(MainActivity.this,"已经授权",Toast.LENGTH_LONG).show();
        } else {//请求权限方法
            String[] permissions = mPermissionList.toArray(new String[0]);//将List转为数组
            ActivityCompat.requestPermissions(MainActivity.this, permissions, 2);
        }
    }

    //获取相机实例
    public static Camera getCameraInstance(){
        Camera c = null;
        try {
            c = Camera.open(); // attempt to get a Camera instance
        }
        catch (Exception e){
            // Camera is not available (in use or does not exist)
            Log.d(TAG,"Camera is not available");
        }
        return c; // returns null if camera is unavailable
    }

    //打印相机参数
    private void printCameraParameters(){
        //获取可用摄像头的数量
        Log.d(TAG, String.valueOf(Camera.getNumberOfCameras()));

        //获取摄像头信息
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        Log.d(TAG,  "face:"+ cameraInfo.facing + ",orientation:" + (cameraInfo.orientation));

        //获取相机参数
        Camera.Parameters parameters = mCamera.getParameters();
        List<Camera.Size> supportedSizes = parameters.getSupportedPreviewSizes();
        for(Camera.Size previewSize : supportedSizes){  //打印预览支持尺寸
            Log.d(TAG,"preview size:" + String.valueOf(previewSize.width) + "*" + String.valueOf(previewSize.height) + " 比例为：" + String.valueOf((float)previewSize.width / previewSize.height));
        }
        supportedSizes.clear();
        supportedSizes = parameters.getSupportedPictureSizes();
        for(Camera.Size pictureSize : supportedSizes){  //打印照片支持尺寸
            Log.d(TAG,"picture size:" + String.valueOf(pictureSize.width) + "*" + String.valueOf(pictureSize.height) + " 比例为：" + String.valueOf((float)pictureSize.width / pictureSize.height));
        }
        //打印预览支持格式
        List<Integer> supportedPreviewFormat = parameters.getSupportedPreviewFormats();
        for(Integer previewFormat : supportedPreviewFormat){
            switch (previewFormat){
                case 17 : Log.d(TAG,"preview format:NV21");break;
                case 842094169 : Log.d(TAG,"preview format:YV12");break;
                default:
            }
        }
        //打印照片支持格式
        List<Integer> supportedPictureFormat = parameters.getSupportedPictureFormats();
        for(Integer pictureFormat : supportedPictureFormat){
            switch(pictureFormat){
                case ImageFormat.JPEG : Log.d(TAG,"picture format : JPEG");break;
                default :
            }
        }
        //打印预览帧率
        List<Integer> previewRate = parameters.getSupportedPreviewFrameRates();
        for(Integer rate : previewRate){
            Log.d(TAG,"preview frame rates : " + String.valueOf(rate));
        }
    }

    //更新相机参数
    private void updateCameraParameters(){
        if(mCamera == null){
            return;
        }

        //获取比例标准，此处，按照竖屏模式（因为竖屏后，SurfaceView 的宽高发生对调了）
        float ratio = (float) mSurfaceView.getHeight() / mSurfaceView.getWidth();

        Log.d(TAG,"标准比例：" + mSurfaceView.getHeight() + "x" + mSurfaceView.getWidth() + "," + ratio);

        //获取修改参数的实例
        Camera.Parameters p = mCamera.getParameters();

        //设置照片尺寸
        Camera.Size realSize = null;
        List<Camera.Size> supportedSizes = p.getSupportedPictureSizes();
        for(Camera.Size size : supportedSizes){
            if(size.width == 1280 && size.height == 960){   //此处设置照片尺寸（1280x960）
                realSize = size;
                break;
            }
        }
        assert realSize != null;
        Log.d(TAG,"real picture size : " + String.valueOf(realSize.width) + "*" + String.valueOf(realSize.height));
        p.setPictureSize(realSize.width,realSize.height);
        pictureSize = realSize; //获取照片尺寸
        //设置预览尺寸
        realSize = null;
        supportedSizes.clear();
        supportedSizes = p.getSupportedPreviewSizes();
        for(Camera.Size size : supportedSizes){
            if(size.width == 960 && size.height == 720){    //此处设置预览尺寸（960x720）
                realSize = size;
                break;
            }
        }
        assert realSize != null;
        Log.d(TAG,"real preview size : " + String.valueOf(realSize.width) + "*" + String.valueOf(realSize.height));
        p.setPreviewSize(realSize.width,realSize.height);
        previewSize = realSize; //获取预览尺寸
        //设置照片格式
        p.setPictureFormat(ImageFormat.JPEG);
        //设置预览格式
        p.setPreviewFormat(ImageFormat.NV21);
        //设置预览帧率
        p.setPreviewFrameRate(30);

        //设置对焦模式
        p.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);    //用于拍照的连续自动对焦模式

        //应用参数
        mCamera.setParameters(p);
    }

    //预览帧保存函数
    private void onGetYUVFrame(byte[] bytes){

        @SuppressLint("SdCardPath") String path = "/sdcard/b1_" + previewSize.width + "x" + previewSize.height + ".nv21";
        File tempFile = new File(path);  //创建文件对象
        try{
            if(! tempFile.exists()){
                //创建文件
                try{
                    FileOutputStream out = new FileOutputStream(tempFile);  //若文件不存在，则创建并写入第一帧数据
                    out.write(bytes);
                    out.close();
                    //Log.d(TAG,"create_file_succeed");
                }catch (IOException e){
                    e.printStackTrace();
                    Log.d(TAG,"create_file__fail");
                }
            } else{
                //追加数据
                RandomAccessFile randomFile = new RandomAccessFile(tempFile,"rw");  //若文件存在，则以追加的方式写入数据
                long fileLength = randomFile.length();
                randomFile.seek(fileLength);
                randomFile.write(bytes);
                randomFile.close();
                //Log.d(TAG,"store_normal");
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Log.d(TAG,"store_file");
        } catch (IOException e) {
            e.printStackTrace();
            Log.d(TAG,"store_io");
        }
    }

    //照片保存函数
    private void onTakePicture(byte[] bytes){
        @SuppressLint("SdCardPath") String path = "/sdcard/bp1_" + pictureSize.width + "x" + pictureSize.height + ".jpg";
        File tempFile = new File(path);
        try {
            FileOutputStream fos = new FileOutputStream(tempFile);
            fos.write(bytes);
            fos.close();
            Log.d(TAG,"save succeeded");
        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }

        //拍照成功提示
        Toast.makeText(MainActivity.this,"照片已保存",Toast.LENGTH_SHORT).show();

        //重新开始预览（Camera.takePicture 的调用会隐式执行 Camera.stopPreview()，预览参数不变 ）
        mCamera.startPreview();
    }
}
